home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / pctj0487.arc / CE_TEST.ASM < prev    next >
Assembly Source File  |  1987-02-17  |  15KB  |  407 lines

  1. ;====================================================================
  2. ; CE_TEST                Dan Rollins                December 15, 1986
  3. ; This program illustrates techniques for intercepting and replacing
  4. ; the DOS Critical Error handler.  It shows how to:
  5. ;    * save and restore the application screen
  6. ;    * make the error message popup in a window
  7. ;    * allow the error handler to return directly to the application
  8. ;      program, passing back a DOS error code (even for DOS 2.x).
  9. ;
  10. ; After installing an INT 24H handler, it attempts to open a file on
  11. ; drive A, then attempts to send characters to the printer.
  12. ;
  13. ; This is a COM-format program and must be processed with EXE2BIN
  14.  
  15. ;=====================================================================
  16. ; MACROS used in this listing
  17. ;=====================================================================
  18. $set_csr macro   line,clm            ;;this positions the cursor
  19.          mov     dx,((line)*256)+clm
  20.          mov     ah,2
  21.          mov     bh,0
  22.          int     10H
  23.          endm
  24. $disp    macro   string              ;;this displays a string
  25.         ifnb    <string>
  26.           mov     dx,offset string   ;;if string given, point DX to it
  27.         endif                        ;; otherwise, assume DX is set
  28.          call    disp_msg
  29.          endm
  30. ;=====================================================================
  31. ; Code and data to install and test the error handler.  This is
  32. ; the "application program" that is disrupted by a critical error.
  33. ;=====================================================================
  34. code_seg segment
  35.          assume  cs:code_seg, ds:code_seg, es:code_seg
  36.          org     100H          ;must have for COM-format programs
  37.  
  38. ce_test  proc    near
  39.          jmp     start
  40.  
  41. filespec    db   "a:\erase.me",0           ;filespec used in disk test
  42.  
  43. test_msg    db   "This is a test message ",0dh,0ah ;for printer test
  44. MSG_LEN     equ  ($-test_msg)
  45.  
  46. prtr_msg    db   "Printer error test.  Press a key...",0
  47. disk_msg    db   "Disk A: error test. Press a key...",0
  48. new_line    db   0dh,0ah,0
  49.  
  50. no_err_msg  db   "Returned from DOS function without error.",0dh,0ah,0
  51. ret_err_msg db   "Error "
  52. ret_code    dw   ?              ;this is filled with 2 ASCII digits
  53.             db   " upon return from DOS function.",0ah,0dh,0
  54.  
  55. start:   mov     al,24H         ;DOS critical error interrupt number
  56.          mov     ah,25H         ;function to replace an int vector
  57.          mov     dx,offset crit_err
  58.          int     21H            ;local error handler is in place
  59.  
  60.          $disp   disk_msg       ;display a message and await a key
  61.          call    get_key
  62.          $disp   new_line
  63.  
  64.          ;------ disk test just attempts to open a file on drive A
  65.          mov     dx,offset filespec
  66.          mov     cx,0           ;normal attribute
  67.          mov     ah,3cH         ;create file
  68.          int     21H
  69.          jnc     ct_20          ;if no error, continue
  70.  
  71.          push    ax             ;else, stabilise DOS
  72.          mov     ah,19H         ;  with dummy call to function 19H,
  73.          int     21H            ;  get current drive
  74.          pop     ax
  75.          mov     bl,10          ;setup string with error number
  76.          div     bl
  77.          add     ax,3030H       ;force binary to ASCII
  78.          mov     ret_code,ax
  79.          $disp   ret_err_msg    ;and display the resulting string
  80.          jmp     ct_30
  81. ct_20:
  82.          $disp   no_err_msg
  83.  
  84. ct_30:   ;------ printer test sends text to standard printer device
  85.          $disp   prtr_msg      ;display a message and await a key
  86.          call    get_key
  87.          $disp   new_line
  88.          mov     bx,4          ;handle reserved for standard printer
  89.          mov     cx,MSG_LEN
  90.          mov     dx,offset test_msg
  91.          mov     ah,40H        ;DOS write_handle function
  92.          int     21H
  93.          jnc     ct_40         ;if no error, continue
  94.  
  95.          push    ax            ;else, stabilise DOS
  96.          mov     ah,19H        ;  with dummy call to function 19h,
  97.          int     21H
  98.          pop     ax
  99.          mov     bl,10         ;setup string with error number
  100.          div     bl
  101.          add     ax,3030H
  102.          mov     ret_code,ax
  103.          $disp   ret_err_msg   ;  and display it
  104.          jmp     ct_exit
  105. ct_40:
  106.          $disp   no_err_msg
  107.  
  108. ct_exit: mov     ah,4cH        ;DOS exit function
  109.          int     21H
  110. ce_test  endp
  111.  
  112. ;=====================================================================
  113. ; Start of Critical Error handler code and data
  114. ;=====================================================================
  115. WIN_TOP  equ     10            ;these equate describe the popup
  116. WIN_LEFT equ     20            ;window used by the error handler
  117. WIN_HIGH equ     4
  118. WIN_WIDE equ     40
  119. WIN_ATTR equ     70H           ;reverse video screen attribute
  120.  
  121. devhdr_addr label dword        ;these values are saved upon entry
  122. devhdr_off       dw ?
  123. devhdr_seg       dw ?
  124. save_ax          dw ?
  125. save_di          dw ?
  126.  
  127. save_sp          dw ?          ;these are used in a CANCEL request
  128. app_err          dw ?
  129.  
  130. response_msg     db "Retry or Cancel? (press R or C) ",0
  131.  
  132. crit_err proc    far
  133.          mov     cs:save_sp,sp   ;save the stack position at start
  134.          push    ax              ;save DOS's registers
  135.          push    bx
  136.          push    cx
  137.          push    dx
  138.          push    si
  139.          push    di
  140.          push    bp
  141.          push    es
  142.          push    ds
  143.  
  144.          push    cs
  145.          pop     ds
  146.          mov     devhdr_off,si   ;save address of the device header
  147.          mov     devhdr_seg,bp
  148.          mov     save_ax,ax      ;save err type & read/write bit flags
  149.          mov     save_di,di      ;save error code
  150.  
  151.          and     di,00ffH        ;get critical error code
  152.          add     di,19           ;convert to DOS error code
  153.          mov     app_err,di      ;save in case we return directly to
  154.                                  ; the interrupted application
  155.          call    save_scrn
  156.          call    clr_window
  157.  
  158.          mov     ax,save_ax
  159.          test    ah,80H          ;disk error ?
  160.          jnz     ce_10           ; no, process character device error
  161.          call    disk_err        ; yes, process disk error
  162.          jmp     ce_20
  163. ce_10:   call    char_err
  164. ce_20:
  165.          $set_csr <WIN_TOP+3>,<WIN_LEFT+1>
  166.          $disp   response_msg  ;display "Retry or Cancel" message
  167.  
  168.  
  169. ce_30:   call    get_key
  170.          or      al,32         ;force response to lowercase
  171.          cmp     al,'c'        ;request to Cancel?
  172.          je      ce_50         ; yes, go
  173.          cmp     al,'r'        ;request to Retry?
  174.          je      ce_40
  175.  
  176.          call    beep          ;else, invalid response
  177.          jmp     ce_20         ;go back an wait for a vaild response
  178.  
  179. ce_40:   ;-------------------- action taken on RETRY request
  180.          call    restore_scrn  ;leave screen as it was before error
  181.          pop     ds            ;restore DOS registers
  182.          pop     es
  183.          pop     bp
  184.          pop     si
  185.          pop     di
  186.          pop     dx
  187.          pop     cx
  188.          pop     bx
  189.          pop     ax
  190.          mov     al,1          ;set "Retry" return code
  191.          iret                  ;and exit to DOS
  192.  
  193. ce_50:   ;--------------------- action taken on CANCEL request
  194.          call    restore_scrn  ;leave screen as it was before error
  195.          mov     sp,cs:save_sp ;locally-saved regs are irrelevant
  196.          pop     ax            ;and discard DOS IP
  197.          pop     ax            ;            DOS CS
  198.          pop     ax            ;            DOS flags
  199.  
  200.          pop     ax            ;restore application's registers
  201.          pop     bx
  202.          pop     cx
  203.          pop     dx
  204.          pop     si
  205.          pop     di
  206.          pop     bp
  207.          pop     ds
  208.          pop     es
  209.  
  210.          push    bp                 ;set the carry flag (on the stack)
  211.          mov     bp,sp              ; so the application will
  212.          or      word ptr [bp+6],1  ; notice that an error occurred
  213.          pop     bp
  214.          mov     ax,cs:app_err      ;and pass back a DOS error code
  215.          iret
  216. crit_err endp
  217.  
  218. ;=====================================================================
  219. ; Start of  code and data specific to character device errors
  220. ;=====================================================================
  221. gen_msg          db "General failure on ",0
  222. paper_msg        db "Printer out of paper on ",0
  223. read_msg         db "Error reading from ",0
  224. write_msg        db "Error writing to ",0
  225. device_msg       db "device '"
  226. dev_name         db 9 dup(?)
  227.  
  228. char_err proc    near
  229.          $set_csr <WIN_TOP+1>,<WIN_LEFT+1>
  230.  
  231.          mov     bx,save_di        ;fetch the error code
  232.          mov     dx,offset gen_msg ; assume "general failure" error
  233.          cmp     bl,9              ; is it a "paper out" error?
  234.          jne     ch_10             ; no, go.
  235.          mov     dx,offset paper_msg
  236. ch_10:   cmp     bl,0aH            ; is it a "write fault" error?
  237.          jne     ch_20             ; no, go.
  238.          mov     dx,offset write_msg
  239. ch_20:   cmp     bl,0bH            ; is it a "read fault" error?
  240.          jne     ch_30             ; no, go.
  241.          mov     dx,offset read_msg
  242. ch_30:   $disp
  243.  
  244.          ;------- now find the name of the malfunctioning device
  245.          push    ds
  246.          lds     si,cs:devhdr_addr
  247.          add     si,0aH        ;point to device name in driver header
  248.          push    cs
  249.          pop     es
  250.          mov     di,offset dev_name  ;point to local buffer for name
  251.  
  252.          mov     cx,8      ; 8 characters max
  253. ch_40:   lodsb             ; get a character
  254.          cmp     al,' '    ;end of device name?
  255.          je      ch_50     ; yes, go
  256.          stosb             ; no, add to local string
  257.          loop    ch_40     ; get next character
  258. ch_50:
  259.          pop     ds
  260.  
  261.          mov     al,"'"    ;close quote on the device name: 'PRN'
  262.          stosb
  263.          mov     al,0      ; and make string ASCIIZ
  264.          stosb
  265.  
  266.          $disp   device_msg
  267.          ret
  268. char_err endp
  269.  
  270.  
  271. ;=====================================================================
  272. ; Start of code and data specific to disk errors
  273. ;=====================================================================
  274. disk_read_msg    db "Disk read ",0
  275. disk_write_msg   db "Disk write ",0
  276. disk_err_msg     db "error on drive "
  277. disk_id          db "A:",0
  278.  
  279. write_prot_msg   db "Disk is write-protected.",0
  280. not_ready_msg    db "Drive door may be open.",0
  281. bad_media_msg    db "The disk media seems to be flawed.",0
  282. gen_fail_msg     db "General failure of the drive.",
  283.  
  284. disk_msg_tbl     dw write_prot_msg, gen_fail_msg, not_ready_msg ;1,2,3
  285.                  dw gen_fail_msg, bad_media_msg, gen_fail_msg   ;4,5,6
  286.                  dw bad_media_msg, bad_media_msg, bad_media_msg ;7,8,9
  287.                  dw gen_fail_msg, gen_fail_msg, gen_fail_msg    ;a,b,c
  288.                  dw gen_fail_msg                                ;d
  289.  
  290. disk_err proc    near
  291.          $set_csr <WIN_TOP+1>,<WIN_LEFT+1>
  292.  
  293.          mov     ax,save_ax
  294.          add     al,'A'
  295.          mov     disk_id,al
  296.  
  297.          mov     dx,offset disk_read_msg ;assume read error
  298.          test    ah,1
  299.          jz      de_10
  300.          mov     dx,offset disk_write_msg
  301. de_10:   $disp                ;display "Disk Write " or "Disk Read "
  302.  
  303.          $disp   disk_err_msg ;display "error on drive x:"
  304.          $set_csr <WIN_TOP+2>,<WIN_LEFT+1>
  305.  
  306.          mov     bx,save_di     ;look up which message to display
  307.          mov     bh,0
  308.          shl     bx,1           ;each address entry is 2 bytes long
  309.          mov     dx,disk_msg_tbl[bx]
  310.          $disp
  311.          ret
  312. disk_err endp
  313. ;=====================================================================
  314. ; Start of general-purpose and library routines
  315. ;=====================================================================
  316.  
  317. include ce_conio.asm              ;insert console I/O routines
  318.  
  319. ;---------------------------------------------------------------------
  320. ; CLR_WINDOW
  321. ; This function clears the error message window.
  322. ; Window position, size, and display attributes are set by equates.
  323. ;---------------------------------------------------------------------
  324. clr_window proc  near
  325.          mov     ch,WIN_TOP
  326.          mov     cl,WIN_LEFT
  327.          mov     dh,WIN_TOP + WIN_HIGH
  328.          mov     dl,WIN_LEFT + WIN_WIDE
  329.          mov     bh,WIN_ATTR
  330.          mov     al,0             ; AL=0 means clear window
  331.          mov     ah,6             ;BIOS scroll_window service
  332.          int     10H
  333.          ret
  334. clr_window endp
  335.  
  336. ;---------------------------------------------------------------------
  337. ; SAVE_SCRN
  338. ; This function save's the application's screen
  339. ; and cursor position.  Doesn't work for graphics-mode screens
  340. ;---------------------------------------------------------------------
  341. save_scrn proc   near
  342.          push    ds
  343.          push    es
  344.  
  345.          mov     bh,0               ;assume video page 0
  346.          mov     ah,3
  347.          int     10H                ;get cursor position
  348.          mov     cs:save_csr,dx     ;save for restore_scrn function
  349.  
  350.          int     11H                ;locate video memory segment
  351.          mov     bx,0b800H          ;assume color card
  352.          and     ax,30H
  353.          cmp     ax,30H
  354.          jne     sc_10
  355.          mov     bx,0b000H          ;must be mono card
  356. sc_10:
  357.          mov     cs:scrn_seg,bx     ;save for restore_scrn function
  358.  
  359.          mov     ds,bx              ;source is video memory
  360.          mov     si,0
  361.          push    cs                 ;destination is local scrn buffer
  362.          pop     es
  363.          mov     di,offset scrn_buf
  364.          mov     cx,2000            ;count of words on entire screen
  365.         rep movsw
  366.  
  367.          pop     es
  368.          pop     ds
  369.          ret
  370. save_scrn endp
  371.  
  372. ;---------------------------------------------------------------------
  373. ; RESTORE_SCRN
  374. ; this function restore's the application's screen
  375. ; and cursor position
  376. ;---------------------------------------------------------------------
  377. restore_scrn proc near
  378.          push    ds
  379.          push    es
  380.  
  381.          mov     dx,cs:save_csr     ;fetch application's cursor pos
  382.          mov     ah,2
  383.          mov     bh,0               ;assume video page 0
  384.          int     10H                ;set cursor position
  385.  
  386.          push    cs                 ;source is local screen storage
  387.          pop     ds
  388.          mov     si,offset scrn_buf
  389.  
  390.          mov     es,cs:scrn_seg     ;destination is video memory
  391.          mov     di,0
  392.          mov     cx,2000            ;count of words on entire screen
  393.         rep movsw
  394.  
  395.          pop     es
  396.          pop     ds
  397.          ret
  398. restore_scrn endp
  399.  
  400. scrn_seg dw  ?                  ;used by save_scrn and restore_scrn
  401. save_csr dw  ?
  402. scrn_buf label   word           ;local screen storage begins here
  403.  
  404. code_seg ends
  405.          end     ce_test
  406.  
  407.